package matching_sequencial;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Scanner;

import uk.ac.shef.wit.simmetrics.similaritymetrics.JaroWinkler;
import uk.ac.shef.wit.simmetrics.similaritymetrics.Levenshtein;
import uk.ac.shef.wit.simmetrics.similaritymetrics.QGramsDistance;
import uk.ac.shef.wit.simmetrics.similaritymetrics.Soundex;

public class Matching {
	private ArrayList<String> source;
	private ArrayList<String> target;
	private int numberOfPairComparation;
	private static String CONTAINER_NAME;
	private static String OUTPUT;
	private static String INPUT;
	
	public Matching(String source, String target, int numberOfPairComparation, String CONTAINER_NAME, String OUTPUT, String INPUT) {
		this.CONTAINER_NAME = CONTAINER_NAME;
		this.OUTPUT = OUTPUT;
		this.INPUT = INPUT;
		
		try {
			this.source = readFile(source);
			this.target = readFile(target);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.numberOfPairComparation = numberOfPairComparation;
	}
	
	public int doMatching(Double threshold) throws IOException {
		ArrayList<String> alignment = new ArrayList<String>();
		int comparations = 0;
		for (String conceptSource : source) {
			Double similarity;
			Double maxSimilarity = 0.0;
			String out = "";
			
			for (String conceptTarget : target) {
				similarity = ComputeMatchers(conceptSource, conceptTarget, threshold);
				comparations++;
				//allComparations += filesDataSource.getName() + " - " + fileTarget.getName() + "\n";
				if (similarity != null && similarity > maxSimilarity) {
					maxSimilarity = similarity;
					out = numberOfPairComparation + ": " + conceptSource + " - " + conceptTarget + " = " + formatDecimal(similarity) + "\n";
				}
			}
			
			if (!out.isEmpty()) {
				FileWriter fw = new FileWriter("human_mouse_string.txt", true);  
	            BufferedWriter conexao = new BufferedWriter(fw);  
	            conexao.write(out);  
	            conexao.newLine();  
	            conexao.close();
				
			}
			
			
		}
		
		return comparations;
	}
	
	private String formatDecimal(Double similarity) {
		return (similarity == null ? "" : new DecimalFormat("#.##").format(similarity));
	}

	private Double ComputeMatchers(String conceptSource, String conceptTarget,
			Double threshold) {
		String labelSource = formatLabel(conceptSource);
		String labelTarget = formatLabel(conceptTarget);
		
		double gramSimilarity = new QGramsDistance().getSimilarity(labelSource, labelTarget);
//		double cosineSimilarity = new CosineSimilarity().getSimilarity(labelSource, labelTarget);
//		double jaccardSimilarity = new JaccardSimilarity().getSimilarity(labelSource, labelTarget);
		double jaroWinklerSimilarity = new JaroWinkler().getSimilarity(labelSource, labelTarget);
		double levenshteinSimilarity = new Levenshtein().getSimilarity(labelSource, labelTarget);
		double soundexSimilarity = new Soundex().getSimilarity(labelSource, labelTarget);
//		double diceSimilarity = new DiceSimilarity().getSimilarity(labelSource, labelTarget);
		
		double linguisticSimilarity = (gramSimilarity + jaroWinklerSimilarity + levenshteinSimilarity + soundexSimilarity) / 4;

		if (linguisticSimilarity >= threshold) {
			return linguisticSimilarity;
		}
		return null;

	}
	
	private static String formatLabel(String nameToString) {
		nameToString = nameToString.toLowerCase().replace("_", " ");
		return nameToString;
	}
	
	private static ArrayList<String> readFile(String path) throws Exception {
		File f = new File(path);
		
		ArrayList<String> listConcepts = new ArrayList<String>();
		Scanner in = new Scanner(new FileReader(f));
		in.nextLine();
		while (in.hasNextLine()) {
		    String line = in.nextLine();
		    listConcepts.add(line);
		}
		
		return listConcepts;
	}

}
